<?php

namespace App\Services\Sale;

use App\CodeResponse;
use App\Enum;
use App\Models\Basic\Product;
use App\Models\Sale\SaleItem;
use App\Models\Sale\SaleOrder;
use App\Models\Stock\ProductStock;
use App\Repositories\Sale\SaleOrderRepository;
use App\Services\BaseService;
use App\Services\Basic\ShopService;
use App\Services\Basic\StorageService;
use App\Services\Stock\ProductStockService;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class SaleOrderService extends BaseService
{

    protected $shopId;//店铺ID
    protected $storageId;//仓库ID

    protected $saleProducts;//销售商品集

    protected $createOrderItemData;//创建订单子项目数据集
    protected $saleStockItems;//订单库存处理子项目数据集


    public function createOrderWithCashPay($params)
    {

        $this->checkParams($params);
        //获取操作用户ID
        $params['user_id'] = get_user_id();
        DB::beginTransaction();
        try {
            //生成单号
            $params['order_no'] = $this->generateNo();

            //计算订单销售总价，计算订单成本总价
            $params['total_sale_price'] = $this->saleProducts->sum('total_sale_price');
            $params['total_cost_price'] = $this->saleProducts->sum('total_cost_price');
            $params['status'] = Enum::SALE_ORDER_STATUS_PAID;

            $saleOrder = app(SaleOrderRepository::class)->create($params);
            // 构造创建订单子项目和订单库存处理子项目数据集
            $this->makeOrderHandleData($saleOrder);

            //添加订单子项目
            SaleItem::query()->insert($this->createOrderItemData->toArray());

            //扣减库存并添加销售出库记录

            ProductStockService::getInstance()->initData($this->saleStockItems, $this->storageId)->handleSaleOut();
            DB::commit();
            return $saleOrder;

        } catch (QueryException $exception) {
            DB::rollBack();
            Log::error($exception->getMessage());
            return false;
        }

    }

    public function checkParams($params)
    {
        $this->shopId = $params['shop_id'];
        $this->storageId = ShopService::getInstance()->getStorageId($this->shopId);
        if (!StorageService::getInstance()->isValid($this->storageId)) {
            return $this->throwBusinessException(CodeResponse::PARAM_ILLEGAL, '找不到对应的仓库');
        }
        //检查商品是否有效并 检查商品门店库存是否足够
        $this->checkOrderProducts($params['products']);
    }


    protected function checkOrderProducts($items)
    {
        //获取全部商品ID
        $productIdToNums = array_column($items, 'num', 'product_id');
        $productIds = array_keys($productIdToNums);
        //获取全部product,检查商品有效性
        $products = Product::whereIn('id', $productIds)->select(['id', 'name', 'supplier_id', 'status', 'sale_price'])->get();
        $deListing = $products->where('status', Enum::PRODUCT_STATUS_DE_LISTING)->first();
        if ($deListing) {
            $this->throwBusinessException(CodeResponse::PARAM_ILLEGAL, '产品' . $deListing['name'] . '已下架');
        }

        //获取全部product-stocks，检查库存
        $productStocks = ProductStock::query()->select(['product_id', 'storage_id', 'num', 'cost_price'])
            ->whereIn('product_id', $productIds)
            ->where('storage_id', $this->storageId)
            ->get();

        if (count($productIds) !== $products->count() || count($productIds) !== $productStocks->count()) {
            $this->throwBusinessException(CodeResponse::PARAM_ILLEGAL, '产品参数错误');
        }

        $this->saleProducts = $productStocks->map(function ($item) use ($productIdToNums, $products) {
            $productId = $item['product_id'];
            if ($item['num'] < $productIdToNums[$productId]) {
                $product = $products->where('id', $productId)->first();
                $this->throwBusinessException(CodeResponse::PARAM_ILLEGAL, '商品' . $product['name'] . '库存不足');
            }
            $product = $products->where('id', $productId)->first();
            return [
                'product_id' => $productId,
                'num' => $productIdToNums[$productId],
                'sale_price' => $product['sale_price'],
                'total_sale_price' => cal_total_price($product['sale_price'], $item['num']),
                'cost_price' => $item['cost_price'],  //当前库存成本价
                'total_cost_price' => cal_total_price($item['cost_price'], $item['num']),
            ];
        });
        return true;
    }

    //构造创建订单子项目和订单库存处理子项目数据集
    public function makeOrderHandleData($saleOrder)
    {
        $this->createOrderItemData = collect();
        $this->saleStockItems = collect();
        $this->saleProducts->map(function ($item) use ($saleOrder) {

            $this->createOrderItemData->push([
                'order_id' => $saleOrder['id'],
                'product_id' => $item['product_id'],
                'num' => $item['num'],
                'sale_price' => $item['sale_price'],
                'total_sale_price' => $item['total_sale_price'],
                'cost_price' => $item['cost_price'],
                'total_cost_price' => $item['total_cost_price'],
                'created_at'=>date('Y-m-d H:i:s'),
                'updated_at'=>date('Y-m-d H:i:s')
            ]);

            $this->saleStockItems->push([
                'product_id' => $item['product_id'],
                'num' => $item['num'],
                'price' => $item['cost_price'],
                'total_price' => $item['total_cost_price']
            ]);


        });

    }

    public function generateNo()
    {
        return retry(5, function () {
            $randomNumber = str_pad(random_int(1, 9999), 4, '0', STR_PAD_LEFT);
            $no = 'SH' . date('YmdHis') . $randomNumber;
            $flag = SaleOrder::query()->where('order_no', $no)->exists();
            if (!$flag) {
                return $no;
            }
            $this->throwBusinessException(CodeResponse::FAIL, '订单号获取失败');
        });
    }


}